﻿#include "UdpClient.h"
#include <QRegularExpression>

#pragma execution_character_set("utf-8")

UdpClient::UdpClient(QObject *parent) : ComBase(parent)
{
    qRegisterMetaType<QAbstractSocket::SocketState>("QAbstractSocket::SocketState");
    mUdpSocket = new QUdpSocket(this);//初始化socket
    connect(mUdpSocket, &QUdpSocket::readyRead, this, &UdpClient::onReadyRead);
    connect(mUdpSocket,&QUdpSocket::stateChanged,this, &UdpClient::onStateChanged);
#if QT_VERSION >= 0x060000
    // Qt 6 的代码
    connect(mUdpSocket, &QAbstractSocket::errorOccurred, this, &UdpClient::onErrorOccurred);
#else
    // Qt 5 的代码
    connect(mUdpSocket, QOverload<QAbstractSocket::SocketError>::of(&QAbstractSocket::error), this, &UdpClient::onErrorOccurred);
#endif
}

void UdpClient::onInit()
{
    if(mUdpSocket == nullptr){
        qDebug() << "udp not init!";
        return;
    }
    if(mUdpSocket->state() == QAbstractSocket::BoundState){
        mUdpSocket->abort();
    }
    bool isBindSuccess = false;
    switch(mConfig.udp.mSendType){
    case UST_Unicast:
        isBindSuccess = mUdpSocket->bind(QHostAddress(mConfig.udp.mLocalIP), mConfig.udp.mLocalPort);
        break;
    case UST_Broadcast:
        isBindSuccess = mUdpSocket->bind(QHostAddress::AnyIPv4, mConfig.udp.mLocalPort);
        break;
    case UST_Multicast:
        isBindSuccess = mUdpSocket->bind(QHostAddress::AnyIPv4, mConfig.udp.mLocalPort); //根据Qt示例，组播的话IPv4和v6分开的
//        mUdpSocket->joinMulticastGroup(QHostAddress(mConfig.udp.mLocalIP));
        //组播的数据的生存期，数据报没跨1个路由就会减1.表示多播数据报只能在同一路由下的局域网内传播
        mUdpSocket->setSocketOption(QAbstractSocket::MulticastTtlOption,1);
        break;
    }
    if(isBindSuccess){
        setState(CS_Connected);
    }
}
void UdpClient::onQuit()
{
    disconnect();
    if(mUdpSocket != nullptr){
        delete  mUdpSocket;
        mUdpSocket = nullptr;
    }
    deleteLater();
}
void UdpClient::disconnect()
{
    if(mUdpSocket->state() == QAbstractSocket::BoundState){
        mUdpSocket->abort();
    }
}

void UdpClient::processData(const QByteArray &data)
{

}

void UdpClient::onReadyRead()
{
    while(mUdpSocket->hasPendingDatagrams()){
        QByteArray datagram;
        datagram.resize(mUdpSocket->pendingDatagramSize());
        mUdpSocket->readDatagram(datagram.data(),datagram.size());
        if(datagram.size() < 1)
            return;
        emit sigReceiveData(datagram);
        processData(datagram);
    }
}

void UdpClient::writeData(const QByteArray& data)
{
    qint64 reply = 0;
    if(mConfig.udp.mSendType == 0){//单播
        reply = mUdpSocket->writeDatagram(data.data(),data.length(),QHostAddress(mConfig.udp.mOpponentIP), mConfig.udp.mOpponentPort);
    } else if(mConfig.udp.mSendType == 1){//广播
        reply = mUdpSocket->writeDatagram(data.data(),QHostAddress::Broadcast,6666);
    } else if(mConfig.udp.mSendType == 2){//组播
        reply = mUdpSocket->writeDatagram(data.data(),QHostAddress(mConfig.udp.mOpponentIP),8888);
    } else {
        return;
    }
    if(reply == -1){
        emit sigMsg(tr("<font color=\'red\'>发送失败:%1</font>") + mUdpSocket->errorString());
    }
}
void UdpClient::onStateChanged(QAbstractSocket::SocketState socketState)
{
    if(socketState == QAbstractSocket::BoundState){
        setState(CS_Connected);
    }else{
        setState(CS_UnConnected);
    }
}

void UdpClient::onErrorOccurred(QAbstractSocket::SocketError error)
{
    QString errStr = QString("error Occurred, errCode: %1, errString: %2").arg(error).arg(mUdpSocket->errorString());
    emit sigMsg(errStr);
}
